#include <iostream>
#include <vector>
#include <string>
#include <mutex>
#include <thread>

using namespace std;

//设计一个类，不能被拷贝
//C++98：拷贝构造+赋值重载设置为私有，只声明不定义
/*
class copyBan{
private:
    copyBan(const copyBan&);
    copyBan& operator=(const copyBan&);
};
*/

//C++11：拷贝构造+赋值重载设置为delete
class copyBan{
public:
    copyBan(const copyBan&) = delete;
    copyBan& operator=(const copyBan&) = delete;
};

//设计一个类，只能在堆上创建对象
//1.将析构函数设为私有，留出一个公共的类似析构的函数
/*
class heapOnly{
public:
    void Destroy(){
        delete this;
    }
private:
    ~heapOnly(){
        std::cout << "~heapOnly()" << std::endl;
    }
};

void test1(){
    //heapOnly h1;
    //static heapOnly h2;
    auto* ph3 = new heapOnly;
    ph3->Destroy();
}
*/

//2.将构造、拷贝构造、赋值重载设为私有
/*
class heapOnly{
public:
    static heapOnly* createObj(){
        auto* p = new heapOnly;
        return p;
    }

private:
    heapOnly(){}

    heapOnly(const heapOnly& hp) = delete;
    heapOnly& operator=(const heapOnly& hp) = delete;
};

void test2(){
    //heapOnly h1;
    //static heapOnly h2;
    //auto* ph3 = new heapOnly;
    auto* ph4 = heapOnly::createObj();
    //heapOnly h3(*ph4);
}

//设计一个类，只能在栈上创建对象
class stackOnly{
public:
    static stackOnly createObj(){
        return stackOnly();
    }

    stackOnly(stackOnly&& st){}

private:
    stackOnly()= default;

    stackOnly(const stackOnly& st) = delete;
};

void test3(){
    //stackOnly st1;
    //static stackOnly st2;
    //auto* ps1 = new stackOnly;
    stackOnly st3 = stackOnly::createObj();
    //static stackOnly st4 = st3;
    static stackOnly st5 = std::move(st3);
}

int main() {
    test3();
    return 0;
}
*/

//单例模式

//饿汉模式：一开始（main)函数之前就创建对象

/*
class singleTon{
public:
    static singleTon* getInstance(){
        return _ins;
    }

    void add(const string& str){
        _m.lock();
        _v.push_back(str);
        _m.unlock();
    }

    void print(){
        _m.lock();
        for (auto& s : _v) {
            cout << s << endl;
        }
        cout << endl;
        _m.unlock();
    }

private:
    singleTon()= default;

    vector<string> _v;
    static singleTon* _ins;
    mutex _m;
};

singleTon* singleTon::_ins = new singleTon;

void test1(){
    srand(time(nullptr));
    for (int i = 0; i < 8; ++i) {
        singleTon::getInstance()->add(to_string(rand()));
    }
    singleTon::getInstance()->print();
}
*/

//懒汉模式：第一次访问实例对象时创建

class singleTon{
public:
    static singleTon* getInstance(){
        if (_ins == nullptr){
            _im.lock();
            if (_ins == nullptr){
                _ins = new singleTon;
            }
            _im.unlock();
        }
        return _ins;
    }

    static void delInstance(){
        _im.lock();
        if (_ins){
            delete _ins;
            _ins = nullptr;
        }
        _im.unlock();
    }

    class GC{
    public:
        ~GC(){
            delInstance();
        }
    };

    static GC _gc;

    ~singleTon(){}

    void add(const string& str){
        _vm.lock();
        _v.push_back(str);
        _vm.unlock();
    }

    void print(){
        _vm.lock();
        for (auto& s : _v) {
            cout << s << endl;
        }
        cout << endl;
        _vm.unlock();
    }

private:
    singleTon()= default;

    vector<string> _v;
    mutex _vm;
    static singleTon* _ins;
    static mutex _im;
};

singleTon* singleTon::_ins = nullptr;
mutex singleTon::_im;
singleTon::GC singleTon::_gc;

void test2(){
    srand(time(nullptr));
    int n = 20;
    thread t1([n](){
        for (int i = 0; i < n; ++i) {
            singleTon::getInstance()->add("thread1:" + to_string(rand()));
        }
    });
    thread t2([n](){
        for (int i = 0; i < n; ++i) {
            singleTon::getInstance()->add("thread2:" + to_string(rand()));
        }
    });
    t1.join();
    t2.join();
    singleTon::getInstance()->print();
}

int main(){
    test2();
    return 0;
}